import { fromPairs } from ".";



/**
 * @description 获取url上的query
 * @param {string} type 可选值：history,hash
 * @returns {string}
 */
const getQuery = (type: string = "hash"): string =>
  type === "hash" ? window.location.hash : window.location.search;

/**
 * for example
 * ```js
 * var val = getUrlParams('192.168.1.1?a=1')
 * console.log(val) // {a:'1'}
 * ```
 *
 * @description 获取url上的参数
 * @param {string} type 可选值：history,hash
 * @returns {{[string]?:string}} 返回一个包含所有参数的对象
 *
 */
const getUrlParams = (type: string): Record<string, string> => {
  return fromPairs(_getUrlParams(getQuery(type)));
};
/**
 * for example
 * ```js
 * var val = _getUrlParams('192.168.1.1?a=1')
 * console.log(val) // [['a','1']]
 * ```
 * @description 获取url上的参数
 * @param {string} url
 * @returns [[string,string]] 返回一个包含所有参数的二维数组
 */
const _getUrlParams = (url: string): Array<[string, string]> => {
  const queryNameRegex = new RegExp("[?&]([^&]*)=([^&]*)", "g");
  let paramsArr = url.match(queryNameRegex) ?? [];
  return paramsArr.map((item) => {
    let arr = item.replace(/[?&]/, "").split("=");
    return [arr[0], arr[1]];
  });
};
/**
 * for example
 * ```js
 * var val = getOneUrlParams('192.168.1.1?a=1')
 * console.log(val) // '1'
 * ```
 * @description 获取url上的某个参数
 * @param {string} key 参数名
 * @param {string} type 可选值：history,hash
 * @returns {string} 返回对应的参数
 */
const getOneUrlParams = (key: string, type: string): string | null => {
  const queryNameRegex = new RegExp(`[?&]${key}=([^&]*)(?:&|$)`);
  const url = getQuery(type);
  const queryNameMatch = url.match(queryNameRegex);

  return queryNameMatch ? queryNameMatch[1] : null;
};
/**
 * for example
 * ```js
 * var val = objectToQuery('192.168.1.1?a=1')
 * console.log(val) // '?a=1&b=2'
 * ```
 * @description 对象转query
 * @param {object} obj 要转换的对象
 * @returns {string} 返回转换后的字符串
 */
const objectToQuery = (obj: Record<string, any>): string => {
  type Key = keyof Record<string, any>;
  return `?${Object.keys(obj)
    .map((key: Key) => `${key}=${obj[key]}`)
    .join("&")}`;
};
// 定义WeakMap来作为urlSearchParams的私有属性
// WeakMap特性是只能用对象作为 key，对象销毁，这个键值对就销毁
const privateData = new WeakMap();

/**
 * @description 自实现的URLSearchParams
 * @param {string} type 可选值：history,hash
 * @param {string} url 不传默认为window.location.href
 */
class urlSearchParams {
  url: URL;
  type: string | undefined;

  constructor(type = "hash", url?: string) {
    this.url = new URL(url ?? window.location.href);
    this.setType(type);
    privateData.set(
      this,
      new Map<string, string>(_getUrlParams(this.getQuery()))
    );
  }
  get(key: string) {
    return privateData.get(this).get(key);
  }
  set(key: string, value: string | number) {
    privateData.get(this).set(key, value);
  }
  has(key: string) {
    return privateData.get(this).has(key);
  }
  delete(key: string) {
    privateData.get(this).delete(key);
  }
  keys() {
    return privateData.get(this).keys();
  }
  values() {
    return privateData.get(this).values();
  }
  entries() {
    return privateData.get(this).entries();
  }
  toString() {
    let obj: Record<string, string> = {};
    for (let [k, v] of privateData.get(this)) {
      obj[k] = v;
    }
    return objectToQuery(obj);
  }
  getQuery() {
    return this.type === "hash" ? this.url.hash : this.url.search;
  }
  setType(type: string) {
    this.type = type;
  }
}

export const objToUri = (obj: Record<string, string | number>) => {
	return Object.keys(obj)
		.map(function(k) {
			return k + '=' + obj[k]
		})
		.join('&')
}

